package sweet.mvc.api

import javax.servlet.http.{ HttpServletRequest => JReq, HttpServletResponse => JResp }

/** A HttpServletRequest wrapper that provide scala feature to access request data. */
class Req(val servletReq: JReq){
  lazy val uri = servletReq.getRequestURI
  lazy val url = servletReq.getRequestURL  
  
  /** get a single required parameter value. throw exception if not found */
  def apply(name: String) = {
    val v = servletReq.getParameter(name)
    if(v != null) v else throw new Exception("Required parameter "+name+" not found")
  }
  
  /** A scala iterator that has all parameter names */
  def paramNames = new Iterator[String](){
    val itr = servletReq.getParameterNames
    def hasNext = itr.hasMoreElements
    def next = itr.nextElement.asInstanceOf[String]
  }
  /** get a single option parameter value. throw exception if not found */
  def param(name: String): Option[String] = {
    val v = servletReq.getParameter(name)
    if(v != null) Some(v) else None
  }
  /** get a single parameter value, or use the default if not found.*/
  def param(name: String, default: String) = {
    val v = servletReq.getParameter(name)
    if(v != null) v else default
  }

  /** get a multiple option parameter values. throw exception if not found */
  def params(name: String): Option[Array[String]] = {
    val v = servletReq.getParameterValues(name)    
    if(v != null) Some(v) else None
  }
  /** get a multiple parameter value, or use the default if not found.*/
  def params(name: String, default: String) = {
    val v = servletReq.getParameterValues(name)
    if(v != null) v else default
  }
  /** A scala map of request paramters. */
  def paramMap = sweet.helper.SMap[String, Array[String]](
    servletReq.getParameterMap.asInstanceOf[java.util.Map[String, Array[String]]])
    
  /** get request method type */
  def method = servletReq.getMethod match {
    case "GET" => Get 
    case "POST" => Post
    /*case "HEAD" => Head
    case "Delete" => Delete
    case "OPTIONS" => Options
    case "TRACE" => Trace
    case "PUT" => Put */
    case t@_ => throw new Exception("Unknown method type " + t)
  }
  
  /** Get a session from requuest. Create new One if none exists. */
  def sess = new Sess(servletReq.getSession(true))
  
  /** Get request attribute with a Type. You normally will expose data to View object and don't need
   * to access request attribute for your application level. However this method provide convinience 
   * to retrieve internal sweet variables. */
  def attr[A](name: String) = servletReq.getAttribute(name).asInstanceOf[A]
  
  /** Return a ReqRoute object for this request. */
  def reqRoute = attr[ReqRoute](Constants.REQ_ROUTE_KEY)
}

import javax.servlet.http.HttpSession
/** A HttpSession wrapper */
class Sess(jsess: HttpSession){
  def apply(name: String): AnyRef = {
    val v = jsess.getAttribute(name)
    if (v == null) throw new Exception("Required session attribute "+name+" not found")
    else v
  }
  
  def update(name: String, value: Any){
    jsess.setAttribute(name, value)  
  }
  
  def attr[A](name: String): Option[A] = {
    val v = jsess.getAttribute(name)
    if(v != null) Some(v.asInstanceOf[A]) else None
  }
  
  def remove(name: String): Option[AnyRef] = { 
    val v = jsess.getAttribute(name)
    if(v != null){ jsess.removeAttribute(name); Some(v) }
    else None
  }
}

/** A HttpServletResponse wrapper that provide scala feature to access request data. */
class Resp(val servletResp: JResp){
  def setContentType(t: String) = servletResp.setContentType(t)
  def writer = servletResp.getWriter
  def printWriter = new java.io.PrintWriter(writer)
}

sealed case class ReqMethod
//Save Methods
case class Get extends ReqMethod
/*case class Head extends ReqMethod
case class Options extends ReqMethod
case class Trace extends ReqMethod */

//Idempotent methods
case class Post extends ReqMethod
/*case class Put extends ReqMethod
case class Delete extends ReqMethod */
